import { Component, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core'
import { FormGroup, FormBuilder, FormControl } from '@angular/forms'
import { Observable, of, combineLatest, BehaviorSubject } from 'rxjs'
import { map, take, tap } from 'rxjs/operators'

import { FieldBase } from '../channel-form/field-base.interface'
import { EPaymentBrand, ETradeChannel } from '@shared/enums'
import { I18NService } from '@core'
import { IQRRouteOfStore, MetaData } from '@shared/interfaces/store'
import { EChannelsSwitcherCategory, IChannelMap } from './channels-switcher.interface'
import { ChannelFormService } from '../channel-form/channel-form.service'
import { FieldControlService } from '../channel-form/field-control.service'
import { Currency } from '@shared/interfaces/common'
import { numScale } from 'app/utils/helpers'

@Component({
  selector: 'app-channels-switcher',
  templateUrl: './channels-switcher.component.html',
  styles: [],
})
export class ChannelsSwitcherComponent implements OnInit, OnChanges {
  constructor(
    private fb: FormBuilder,
    private i18n: I18NService,
    private channelFormService: ChannelFormService,
    private fieldControlService: FieldControlService,
  ) {}

  @Input() formGroup: FormGroup = this.fb.group({})

  @Input() channelsMap: IChannelMap

  @Input() metadata: MetaData

  /**
   * 表示卡或者码
   */
  @Input() category: EChannelsSwitcherCategory
  @Input() insCode: string
  @Input() storeCurrencies: Currency[]

  /**
   * 如果为false，会将switch隐藏掉
   */
  @Input() switchable = true

  isSwitchShown = true

  channelField: Map<string, FieldBase<any>[]> = new Map()
  // channel options which user can select one or more than one to open
  availableChannels$: Observable<string[]>
  // checkedChannels$: Observable<string[]>
  isLoadingMap = new Map<string, boolean>()

  _checkedChannels: string[] = []
  checkedChannels$ = new BehaviorSubject(this._checkedChannels)

  ngOnChanges(changes: SimpleChanges): void {
    if (
      this.category &&
      this.insCode &&
      this.channelsMap &&
      this.storeCurrencies &&
      Array.isArray(this.storeCurrencies)
    ) {
      for (const ch of Object.keys(this.channelsMap)) {
        const route = this.channelsMap[ch]
        if (route) {
          this.onOpenSwitchClick(ch as EPaymentBrand, route, this.metadata)
        }
      }
    }

    if (this.channelsMap) {
      this.availableChannels$ = combineLatest(
        of(Object.keys(this.channelsMap)),
        this.checkedChannels$.asObservable(),
      ).pipe(
        map(([all, checked]) => {
          return all.filter(ch => checked.indexOf(ch) < 0)
        }),
        map(chan => chan.sort())
      )
    }
  }

  ngOnInit() {}

  // open channel after click the switch button
  onOpenSwitchClick(paymentBrand: EPaymentBrand, defaultChan?: IQRRouteOfStore, metaData?: MetaData) {
    this.isLoadingMap.set(paymentBrand, true)

    if (!defaultChan) {
      defaultChan = {
        paymentBrand,
        chanCode: paymentBrand,
      }
    }

    // the fee is presented as 0.01 when store in DB, but it should display as 1% on the page
    const temp: IQRRouteOfStore = { ...defaultChan }
    if (typeof temp.fee === 'number' && !Number.isNaN(temp.fee)) {
      temp.fee = numScale(temp.fee, 2)
    }

    this.channelFormService
      .getFieldsAsync(this.category, paymentBrand, this.insCode, this.storeCurrencies, temp, this.metadata)
      .pipe(take(1))
      .subscribe(fields => {
        this.channelField.set(paymentBrand, fields)
        const form = this.fieldControlService.toFormGroup(fields)
        form.addControl('checked', new FormControl(true))
        this.formGroup.addControl(paymentBrand, form)
        this._checkedChannels.push(paymentBrand)
        this.checkedChannels$.next(this._checkedChannels)
      })
  }

  onCloseChannelClick(paymentBrand: EPaymentBrand): void {
    this.isLoadingMap.set(paymentBrand, false)

    const form = this.formGroup.get(paymentBrand) as FormGroup
    form.addControl('checked', new FormControl(false))
    this.formGroup.removeControl(paymentBrand)

    const index = this._checkedChannels.indexOf(paymentBrand)
    this._checkedChannels.splice(index, 1)
    this.checkedChannels$.next(this._checkedChannels)
  }

  getControlsOfOneChannel(paymentBrand: EPaymentBrand): FormGroup {
    const channelCtrl = this.formGroup.get(paymentBrand) as FormGroup

    return channelCtrl
  }

  translatePaymentBrand(brand: EPaymentBrand): string {
    if (!brand) {
      console.error('empty brand')
      return ''
    }
    return this.trans(ETradeChannel[brand])
  }

  trans(key: string, params?: Object): string {
    return this.i18n.fanyi(key, params)
  }
}
